﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using FinosServiceLibrary.Server;
using FinosLibrary;
using System.Runtime.Remoting.Lifetime;
namespace FinosServiceLibrary.Server {
    public class AppLoader : FMarshalByRefObject {
        public App appBelong;
        private Dictionary<string, Invoker> map;
        public List<string> clients;
        public string name { get { return appBelong.name; } }
        public void LoadAssembly(string fullName) {
            Logger.trace("开始加载模块：" + fullName);
            start(Assembly.LoadFrom(fullName).GetTypes());
        }
        public void addClient(string client) {
            clients.Add(client);
            appBelong.AddClient(client);
        }
        public void start(params Type[] types) {
            IEnumerable<Type> messagetypes = from t in types where Attribute.GetCustomAttribute(t, typeof(MessageProcessAttribute)) != null select t;
            map = new Dictionary<string, Invoker>();
            clients = new List<string>();
            foreach (Type messagetype in messagetypes) {
                MessageProcessAttribute[] mpas = messagetype.GetCustomAttributes(typeof(MessageProcessAttribute), true) as MessageProcessAttribute[];
                if (mpas.Length == 0) continue;
                MessageProcessAttribute mpa = mpas[0];
                if (appBelong.original) {
                    if (mpa.myType != MPType.PropServer) continue;
                } else {
                    if (mpa.myType != MPType.Default) continue;
                }
                object logic = Activator.CreateInstance(messagetype);
                if (logic is ServerLogic) (logic as ServerLogic).application = this;
                LogicParse.Parse(logic, map);
            }
        }
        public Client getClientById(string clientId) {
            return appBelong.getClientByID(clientId);
        }
        public void call(string clientId, Package p) {
            getClientById(clientId).call(p.toBytes());
        }
        public void broadCast(Package package) {
            foreach (string conn in clients) {
                call(conn, package);
            }
        }
        public void TraceMessage(params string[] msg) {
            appBelong.TraceMessage(msg);
        }
        public void onDisconnect(string client) {
            doLogic(new Package("onDisconnect", client), client);
            clients.Remove(client);
            appBelong.RemoveClient(client);
        }
        public void doLogic(byte[] bytes, object client) {
            doLogic(bytes.FromJsonTo<Package>(), client);
        }
        public void doLogic(Package p, object client) {
            if (!map.ContainsKey(p.head)) return;
            Logger.trace(p.ToString());
            try {
                Invoker invoker = map[p.head];
                invoker.SetArg(p, client);
                map[p.head].Invoke();
            } catch (Exception e) {
                Logger.error(e.Message);
                TraceMessage(map[p.head].mi.Name + "调用失败（" + e.InnerException == null ? e.Message : e.InnerException.Message + "）");
            }
        }
    }
}
